﻿using FriendAnalyzer.Infrastructure.MachineLearning.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FriendAnalyzer.Infrastructure.MachineLearning.Analysis
{
    public class FacebookUserClassifierFactory
    {
        #region Singleton Definition

        private static readonly Lazy<FacebookUserClassifierFactory> _instance = new Lazy<FacebookUserClassifierFactory>(() => new FacebookUserClassifierFactory());

        private FacebookUserClassifierFactory() { }

        public static FacebookUserClassifierFactory Instance
        {
            get { return _instance.Value; }
        }

        #endregion

        public FacebookUserClassifier Create(UserFeatures[] database, uint leaderCount, double accuracy, double fuzzyness, double maxStepCount, bool tryAvoidLocalOptimum)
        {
            if (tryAvoidLocalOptimum)
            {
                FacebookUserClassifier userClassifier, currentClassifier = null;
                var minObjectiveValue = double.MaxValue;

                for (int i = 0; i < 5; i++)
                {
                    currentClassifier = SetUpUserClassifier(database, leaderCount, accuracy, fuzzyness, maxStepCount);
                    currentClassifier.Compute(true);

                    if(currentClassifier.Error < minObjectiveValue) 
                    {
                        userClassifier = currentClassifier;
                        minObjectiveValue = currentClassifier.Error;
                    }
                }

                userClassifier = SetUpUserClassifier(database, leaderCount, accuracy, fuzzyness, maxStepCount);
                userClassifier.Centroids = currentClassifier.Centroids;
                return userClassifier;
            }
            else
            {
                return SetUpUserClassifier(database, leaderCount, accuracy, fuzzyness, maxStepCount);
            }
        }

        private FacebookUserClassifier SetUpUserClassifier(UserFeatures[] database, uint leaderCount, double accuracy, double fuzzyness, double maxStepCount)
        {
            var userClassifier = new FacebookUserClassifier(database, leaderCount);
            userClassifier.Accuracy = accuracy;
            userClassifier.Fuzzyness = fuzzyness;
            userClassifier.MaxStepCount = maxStepCount;

            return userClassifier;
        }
    }
}
